import { getnode } from "./json-node";
import {fetch} from 'whatwg-fetch'
import {Gen} from "../tools/Data";

export const RequestBodyType = {
    URLSearchParams: 'URLSearchParams',
    FormData: 'FormData',
    Blob: 'Blob',
    ArrayBuffer: 'ArrayBuffer',
    ArrayBufferView: 'ArrayBufferView',
    String: 'String'
};

export var GlobalNetResultNodes = {
    message: 'message',
    data: 'data',
    status: 'status'
};

export var GlobalNetResultPack = {
    message: 'message',
    data: 'data',
    status: 'status'
};

export var GlobalNetStatusCode = {
    success: 1,
    error: 0
};

export var HTTPMethods = {
    get: "GET",
    post: "POST"
};

export var GlobalNetConfig = {
    defaultDomain: '',
    globalMethod: HTTPMethods.get,
    globalHeaderGetter: function (url) {
        return {};
    },

    globalParameterGetter: function (url) {
        return {};
    },

    globalHandleScheme: function (result) {
        let message_node = GlobalNetResultNodes.message;
        let status_node = GlobalNetResultNodes.status;
        let data_node = GlobalNetResultNodes.data;
        let obj = {};

        let pk_msg_node = GlobalNetResultPack.message;
        let pk_data_node = GlobalNetResultPack.data;
        let pk_staus_node = GlobalNetResultPack.status;

        // console.log('gloabel', result);
        try {
            if (status_node in result) {
                console.log("have status");
                if (result.status === GlobalNetStatusCode.success) {
                    obj[pk_staus_node] = GlobalNetStatusCode.success;
                    obj[pk_msg_node] = result[message_node] || "未知错误(Net未获取到message信息)";
                    obj[pk_data_node] = result[data_node] || {};
                } else {
                    obj[pk_staus_node] = result[status_node];
                    obj[pk_msg_node] = result[message_node] || "未知错误(Net未获取到message信息)";
                    obj[pk_data_node] = result[data_node] || {};
                }
            } else {
                obj[pk_staus_node] = GlobalNetStatusCode.error;
                obj[pk_msg_node] = '服务器端未返回status 参数';
                obj[pk_data_node] = result[data_node] || {};
            }
        } catch (e) {
            obj[pk_staus_node] = GlobalNetStatusCode.error;
            obj[pk_msg_node] = `error ${e}`;
            obj[pk_data_node] = result[data_node] || {};
        }
        return obj;
    }

};

export class Net {

    get POST() {
        this.method = HTTPMethods.post;
        return this;
    }

    get GET() {
        this.method = HTTPMethods.get;
        return this;
    }

    get logConfig() {
        this.__logConfig = true;
        return this;
    }

    get logResult() {
        this.__logResult = true;
        return this;
    }

    constructor(url) {
        this.method = HTTPMethods.get;
        this.__url = url;
        this.__logConfig = false;
        this.__logResult = false;
        this.__params = {};
        this.__bodyType = undefined;
        this.__contentTypes = ['charset=utf-8'];
        this.__formatResult = GlobalNetConfig.globalHandleScheme;
        this.__test = undefined;
    }

    setBodyType(requestBodyType) {
        this.__bodyType = requestBodyType;
        return this;
    }

    get bodyFormData() {
        this.setBodyType(RequestBodyType.FormData);
        return this;
    }

    get bodyUrlSearchParams() {
        this.setBodyType(RequestBodyType.URLSearchParams);
        this.appendConentType('application/x-www-form-urlencoded');
        return this;
    }

    then(successBlock) {
        this.successBlock = successBlock;
        return this;
    }

    catch(rejectBlock) {
        this.rejectBlock = rejectBlock;
        return this;
    }

    url(url) {
        this.__url = url;
        return this;
    }

    params(values) {
        this.__params = values || {};
        return this;
    }

    headers(values) {
        this.headers = values || {};
        return this;
    }

    handleScheme(scheme) {
        this.handleScheme = handleScheme;
        return this;
    }

    appendConentType(oneType) {
        this.__contentTypes.push(oneType);
        return this;
    }

    setMethod(val) {
        switch (val.toUpperCase()) {
            case HTTPMethods.get:
                this.method = HTTPMethods.get;
                break;
            case HTTPMethods.post:
                this.method = HTTPMethods.post;
                break;
        }

        return this;
    }

    test(value) {
        this.__test = value;
        return this;
    }

    get __configs() {
        // let df = {
        //     Accept: 'application/json,text/plain,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        //     Connection: 'close'
        // };
        let df = {};

        let config = {
            headers: Object.assign(df,this.headers,GlobalNetConfig.globalHeaderGetter()),
            method: this.method || GlobalNetConfig.globalMethod
        };
        if (this.method.toUpperCase() === "POST") {
            let abody = this.createBody();
            if (abody !== undefined) {
                config.body = abody;
            }
        }

        if (this.__contentTypes.length > 0) {
            config['Content-Type'] = this.__contentTypes.join('; ');
        }
        return config;
    }

    createBody() {
        let dict = this.__params;
        if (Object.keys(dict).length < 1) {
            return undefined;
        }
        let abodyType = this.__bodyType || RequestBodyType.FormData;
        if (this.method.toUpperCase() === 'GET') {
            abodyType = RequestBodyType.URLSearchParams;
        }
        switch (abodyType) {
            case RequestBodyType.FormData:
                let abody = new FormData();
                for (let one in dict) {
                    abody.append(one, dict[one]);
                }
                return abody;
            case RequestBodyType.URLSearchParams:
                let bbody = new URLSearchParams();
                for (let one in dict) {
                    bbody.append(one, dict[one]);
                }
                return bbody.toString();

        }
        return undefined;
    }

    simulate() {
        let delay = 1500;

        let result = {};
        let status = GlobalNetStatusCode.success;
        let data = {};
        let message = "数据加载成功";
        if (this.__test === undefined){
            this.__test = function (p) {
                return {
                    title:Gen.title,
                    content:Gen.text(7),
                    img:Gen.img,
                    name:Gen.name
                }

            }
        }
        if (typeof this.__test === 'object') {
            if (Reflect.has(this.__test, 'error')) {
                status = GlobalNetStatusCode.error;
                message = `${this.__test['error']}`;
            }
            data = Object.assign({}, this.__test);
        } else if (typeof this.__test === 'function') {
            data = this.__test(this.__params);
        } else {
            data = this.__test;
        }

        try {
            let time = data['delay'];
            if (time !== undefined) {
                delay = time;
            }
        } catch (e) {}
        result[GlobalNetResultPack.data] = data;
        result[GlobalNetResultPack.message] = message;
        result[GlobalNetResultPack.status] = status;
        let net = new Promise(function (resolve, reject) {
            if (status === GlobalNetStatusCode.success) {
                setTimeout(function () {
                    resolve(result);
                }, delay);
            } else {
                setTimeout(function () {
                    reject(result);
                }, delay);
            }
        });
        net.then(this.successBlock).catch(this.rejectBlock);
    }
    send(url) {
        if (this.__test !== undefined) {
            this.simulate();
            return;
        }

        let _url = url || this.__url;
        if (GlobalNetConfig.defaultDomain.length > 10) {
            if (!_url.startsWith('http')) {
                _url = GlobalNetConfig.defaultDomain + _url;
                console.log('absolut url:', _url);
            }
        }

        if (this.method.toUpperCase() === 'GET') {
            let abody = this.createBody();
            if (abody !== undefined) {
                _url = _url + '?' + abody.toString();
            }
        }

        let config = this.__configs;
        if (this.__logConfig) {
            console.log(`
            ${config.method}:${_url}\n
            config:`, config);
        }

        let ws = this;
        let net = new Promise(function (resolve, reject) {
            fetch(_url, config).then(response => {
                if (response.status === 404) {
                    reject({ status: GlobalNetStatusCode.error, message: '访问无效（404）', data: {} });
                }
                return response.text();
            }).then(responseJson => {
                let jsonResult = responseJson;
                if (typeof responseJson === typeof '') {
                    jsonResult = JSON.parse(responseJson);
                }
                let obj = ws.__formatResult(jsonResult);
                if (obj.status === GlobalNetStatusCode.success) {
                    resolve(obj);
                } else {
                    reject(obj);
                }
            }).catch(error => {
                let msg = `Net send get cat chatch error:${error}`;
                reject({ status: GlobalNetStatusCode.error, message: msg, data: {} });
            });
        });
        net.then(this.successBlock).catch(this.rejectBlock);
        return net;
    }
}

Net.debug = false;
export function FetchNet(url) {
    return new Net(url);
}
